﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Entidades;
using LogicaNegocio;

namespace PresentacionEscritorio
{
    public partial class frmGenerarAgendaTurnos : Form, IOpcion
    {
        private string opElegida;
        private int cantidadDiasAgenda; //la cantidad de dias por las que tengo que generar la agenda, dependera de un cálculo
        //que incluye de que mes se trata (por 30 o 31 dias) y el periodo seleccionado (1,2 o 3 meses).
        private EspecialidadMedico espMedicoAgenda; //especialidad médico con la que voy a trabajar y a la que voy a generarle agenda
        private ModalidadAtencion modalidadEspecialidadAgenda;
        private List<HorarioAtencion> listaHorariosVigentes;
        private List<FechaImportante> listaFeriados;

        public frmGenerarAgendaTurnos()
        {
            InitializeComponent();
            //cargarGrilla();
        }

        public void setOpcion(string op)
        {
            opElegida = op;
        }

        public string getOpcion()
        {
            return opElegida;
        }

        private void frmGenerarAgendaTurnos_Load(object sender, EventArgs e)
        {
            cargarComboEspecialidades();
            //cargarComboMedicos();
            txtUltimaFechaAgenda.Enabled = false;
            //cargarGrilla();
        }

        private void cargarGrilla()
        {
            TimeSpan horaInicio = new TimeSpan(08, 0, 0);
            TimeSpan horaFin = new TimeSpan(20, 0, 0);
            TimeSpan horaCelda = horaInicio;

            TimeSpan duracionAtencion = new TimeSpan(0, 30, 0);

            while (horaCelda < horaFin)
            {
                int nroFila = grdAgenda.Rows.Add();
                grdAgenda.Rows[nroFila].Cells["HoraDia"].Value = horaCelda;
                grdAgenda.Rows[nroFila].Cells[0].Style.BackColor = Color.DimGray; //celdas de hora

                grdAgenda.Rows[nroFila].Cells[1].Style.BackColor = Color.LightGray; //celda sin turno
                grdAgenda.Rows[nroFila].Cells[2].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[3].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[4].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[5].Style.BackColor = Color.LightGray;

                horaCelda = horaCelda.Add(duracionAtencion);
            }
        }

        private void cargarComboEspecialidades()
        {
            List<Especialidad> listEspecialidadesTurno = GestorEspecialidades.obtenerEspecialidadesPorTurno();
            cmbEspecialidad.DataSource = listEspecialidadesTurno;
            cmbEspecialidad.DisplayMember = "Nombre";
            cmbEspecialidad.ValueMember = "CodEspecialidad";

            if (cmbEspecialidad.Items.Count != 0)
            {
                int IdEsp = Convert.ToInt32(cmbEspecialidad.SelectedValue);
                cargarComboMedicos(IdEsp);
            }
            else
            {
                cmbMedico.DataSource = null;
            }
            cmbEspecialidad.SelectedIndex = -1;
        }

        private void cmbEspecialidad_SelectionChangeCommitted(object sender, EventArgs e)
        {
            int idEsp = int.Parse(cmbEspecialidad.SelectedValue.ToString());

            cargarComboMedicos(idEsp);
        }


        private void cargarComboMedicos(int idEsp)
        {
            List<Medico> list = GestorEspecialidades.ObtenerMedicosDeEspecialidad(idEsp);
            cmbMedico.DataSource = list;
            cmbMedico.DisplayMember = "ApellidoNombre";
            cmbMedico.ValueMember = "Legajo";
            cmbMedico.SelectedIndex = -1;
        }

        private void cmbMedico_SelectedIndexChanged(object sender, EventArgs e)
        {
            GestorMedicos gm = new GestorMedicos();
            if (espMedicoAgenda == null)
                espMedicoAgenda = new EspecialidadMedico();
            //Especialidad espCOmbo =(Especialidad)cmbEspecialidad.SelectedValue;
            espMedicoAgenda.CodEspecialidad = int.Parse(cmbEspecialidad.SelectedValue.ToString());
            //Medico medCombo = (Medico)cmbMedico.SelectedValue;
            espMedicoAgenda.LegajoMedico = long.Parse(cmbMedico.SelectedValue.ToString());
            espMedicoAgenda.FechaUltimoTurno = gm.obtenerFechaUltimoTurno(espMedicoAgenda);

            if (espMedicoAgenda.FechaUltimoTurno == null)
                txtUltimaFechaAgenda.Text = "No hay turnos generados";
            else
                txtUltimaFechaAgenda.Text = espMedicoAgenda.FechaUltimoTurno.Value.Date.ToString("dd/MM/yyyy");
        }

        private void calcularCantidadDiasAgenda(int cantMeses)
        {
            switch (cantMeses)
            {
                case 1:
                    cantidadDiasAgenda = 30;
                    break;
                case 2:
                    cantidadDiasAgenda = 60;
                    break;
                case 3:
                    cantidadDiasAgenda = 90;
                    break;
            }
        }

        private void rdb1Mes_CheckedChanged(object sender, EventArgs e)
        {
            if (rdb1Mes.Checked)
                calcularCantidadDiasAgenda(1);
        }

        private void rdb2Meses_CheckedChanged(object sender, EventArgs e)
        {
            if (rdb2Meses.Checked)
                calcularCantidadDiasAgenda(2);
        }

        private void rdb3Meses_CheckedChanged(object sender, EventArgs e)
        {
            if (rdb3Meses.Checked)
                calcularCantidadDiasAgenda(3);
        }

        private void btnGenerar_Click(object sender, EventArgs e)
        {
            generarAgenda();
        }

        private void generarAgenda()
        {
            GestorAgendaTurnos gAgenda = new GestorAgendaTurnos();
            //Datos que necesito
            DateTime fechaInicioNuevaAgenda;

            List<Turno> listTurnosNuevos = new List<Turno>();

            if (validarDatos())
            {
                //1° validamos si tiene o no agenda hecha antes, y seteamos el punto de partida del cálculo    
                if (espMedicoAgenda.FechaUltimoTurno != null)
                {
                    fechaInicioNuevaAgenda = espMedicoAgenda.FechaUltimoTurno.Value.AddDays(1);
                }
                else //trabajamos con la fecha de inicio como la de hoy
                {
                    fechaInicioNuevaAgenda = DateTime.Now;
                }

                //2° traemos las listas de datos y la modalidad de atencion
                modalidadEspecialidadAgenda = GestorEspecialidades.ObtenerModalidadAtencionEspecialidad(espMedicoAgenda.CodEspecialidad);

                GestorAgendaTurnos gat = new GestorAgendaTurnos();
                listaFeriados = gat.obtenerFeriadosAñoVigente();
                listaHorariosVigentes = gat.obtenerHorariosVigentesEspecialidadMedico(espMedicoAgenda);

                List<Turno> listaTurnosNuevos = new List<Turno>();

                DateTime fechaFinAgenda = fechaInicioNuevaAgenda.AddDays(cantidadDiasAgenda); //fecha de fin de la agenda - fecha maxima

                //validamos cuales debemos usar - filtramos la lista
                foreach (HorarioAtencion item in listaHorariosVigentes)
                {
                    if (fechaInicioNuevaAgenda >= item.FechaVigenciaDesde && item.FechaVigenciaDesde <= fechaFinAgenda)
                    {
                        item.noUsar = false;
                    }
                    else
                        item.noUsar = true;
                }


                //empezamos a ver cada horario
                foreach (HorarioAtencion item in listaHorariosVigentes)
                {
                    DateTime fechaInicioHorario;
                    Turno turnoNuevo = null;

                    if (item.noUsar == false)
                    {
                        //validamos desde cuando tengo que hacer los turnos
                        if (fechaInicioNuevaAgenda == item.FechaVigenciaDesde || fechaInicioNuevaAgenda > item.FechaVigenciaDesde)
                        {
                            fechaInicioHorario = fechaInicioNuevaAgenda;
                        }
                        else
                        {
                            fechaInicioHorario = item.FechaVigenciaDesde;
                        }

                        //validamos desde que dia puedo hacer los turnos
                        if (fechaInicioHorario.DayOfWeek != item.DayWeekHorario)
                        {
                            int nroDiaFechaInicio = 0;
                            int nroDiaHorario = 0;
                            switch (fechaInicioHorario.DayOfWeek)
                            {
                                case DayOfWeek.Friday:
                                    nroDiaFechaInicio = 6;
                                    break;
                                case DayOfWeek.Monday:
                                    nroDiaFechaInicio = 2;
                                    break;
                                case DayOfWeek.Saturday:
                                    nroDiaFechaInicio = 7;
                                    break;
                                case DayOfWeek.Sunday:
                                    nroDiaFechaInicio = 1;
                                    break;
                                case DayOfWeek.Thursday:
                                    nroDiaFechaInicio = 5;
                                    break;
                                case DayOfWeek.Tuesday:
                                    nroDiaFechaInicio = 3;
                                    break;
                                case DayOfWeek.Wednesday:
                                    nroDiaFechaInicio = 4;
                                    break;
                            }

                            switch (item.DayWeekHorario)
                            {
                                case DayOfWeek.Friday:
                                    nroDiaHorario = 6;
                                    break;
                                case DayOfWeek.Monday:
                                    nroDiaHorario = 2;
                                    break;
                                case DayOfWeek.Saturday:
                                    nroDiaHorario = 7;
                                    break;
                                case DayOfWeek.Sunday:
                                    nroDiaHorario = 1;
                                    break;
                                case DayOfWeek.Thursday:
                                    nroDiaHorario = 5;
                                    break;
                                case DayOfWeek.Tuesday:
                                    nroDiaHorario = 3;
                                    break;
                                case DayOfWeek.Wednesday:
                                    nroDiaHorario = 4;
                                    break;
                            }

                            int diferenciaEntreDias = nroDiaFechaInicio - nroDiaHorario;  //positivo: dias hacia atras - negativo: dias hacia adelante
                            if (diferenciaEntreDias > 0)
                            {
                                int diferenciaEntreDiasReal = 7 - diferenciaEntreDias;
                                fechaInicioHorario = fechaInicioHorario.AddDays(diferenciaEntreDiasReal);
                            }
                            else
                            {
                                fechaInicioHorario = fechaInicioHorario.AddDays(Math.Abs(diferenciaEntreDias));
                            }
                        }

                        DateTime fechaTurnoNuevo = fechaInicioHorario;
                        while (!(item.FechaVigenciaHasta != null && fechaTurnoNuevo >= item.FechaVigenciaHasta) && (fechaTurnoNuevo < fechaFinAgenda)) //fechas
                        {
                            TimeSpan duracionModalidad = new TimeSpan(0, modalidadEspecialidadAgenda.DuracionAtencion, 0);
                            TimeSpan horaTurnoNuevo = item.HoraDesde;
                            bool tengoTurnosCreadosEnElDia = false;
                            while (!(horaTurnoNuevo >= item.HoraHasta || horaTurnoNuevo.Add(duracionModalidad) >= item.HoraHasta)) //horas
                            {
                                if (tengoTurnosCreadosEnElDia == false)
                                {
                                    tengoTurnosCreadosEnElDia = true;
                                    DateTime fechaGeneracionTurnoNuevo = DateTime.Now;

                                    turnoNuevo = new Turno();
                                    turnoNuevo.EspMedico = espMedicoAgenda;
                                    turnoNuevo.FechaGeneracion = fechaGeneracionTurnoNuevo;
                                    turnoNuevo.FechaTurno = fechaTurnoNuevo;
                                    turnoNuevo.HoraTurno = horaTurnoNuevo;
                                    turnoNuevo.IdEstadoTurno = 1;
                                    listaTurnosNuevos.Add(turnoNuevo);
                                    turnoNuevo = null;
                                }
                                else
                                {
                                    horaTurnoNuevo = horaTurnoNuevo.Add(duracionModalidad);
                                    DateTime fechaGeneracionTurnoNuevo = DateTime.Now;

                                    turnoNuevo = new Turno();
                                    turnoNuevo.EspMedico = espMedicoAgenda;
                                    turnoNuevo.FechaGeneracion = fechaGeneracionTurnoNuevo;
                                    turnoNuevo.FechaTurno = fechaTurnoNuevo;
                                    turnoNuevo.HoraTurno = horaTurnoNuevo;
                                    turnoNuevo.IdEstadoTurno = 1;
                                    listaTurnosNuevos.Add(turnoNuevo);
                                    turnoNuevo = null;
                                }
                            }//fin whileHoras
                            fechaTurnoNuevo = fechaTurnoNuevo.AddDays(item.FrecuenciaHorario.CantidadDias);
                        }// fin whileFechas
                    }
                }//fin foreach


                //limpiamos los turnos
                List<Turno> listTurnosNuevosDefinitivo = new List<Turno>();
                foreach (Turno item in listaTurnosNuevos)
                {
                    bool esTurnoFeriado = false;
                    foreach (FechaImportante item2 in listaFeriados)
                    {
                        if (item.FechaTurno.Date == item2.Fecha.Date)
                        {
                            esTurnoFeriado = true;
                            break;
                        }
                    }

                    if (!esTurnoFeriado)
                        listTurnosNuevosDefinitivo.Add(item);

                }

                //grabamos los turnos en la bd
                bool res = gAgenda.registrarTurnosDefinitivos(listTurnosNuevosDefinitivo);

                if (res)
                {
                    cargarGrillaConNuevosTurnos(listTurnosNuevosDefinitivo);
                }

                btnGenerar.Enabled = false;
            }
        }

        private void cargarGrillaConNuevosTurnos(List<Turno> listTurnosNuevosDefinitivo)
        {
            TimeSpan horaInicio = obtenerHoraInicioMasTemprana(listTurnosNuevosDefinitivo);
            TimeSpan horaFin = obtenerHoraFinMasTardia(listTurnosNuevosDefinitivo);

            TimeSpan horaCelda = horaInicio; //empieza con la hora inicio la mas tarde

            TimeSpan duracionAtencion = new TimeSpan(0, modalidadEspecialidadAgenda.DuracionAtencion, 0);

            while (horaCelda <= horaFin)
            {
                int nroFila = grdAgenda.Rows.Add();
                grdAgenda.Rows[nroFila].Cells["HoraDia"].Value = horaCelda;
                grdAgenda.Rows[nroFila].Cells[0].Style.BackColor = Color.DimGray; //celdas de hora

                grdAgenda.Rows[nroFila].Cells[1].Style.BackColor = Color.LightGray; //celda sin turno
                grdAgenda.Rows[nroFila].Cells[2].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[3].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[4].Style.BackColor = Color.LightGray;
                grdAgenda.Rows[nroFila].Cells[5].Style.BackColor = Color.LightGray;

                horaCelda = horaCelda.Add(duracionAtencion);
            }

            //cargamos los turnos
            foreach (Turno item in listTurnosNuevosDefinitivo)
            {
                for (int i = 0; i < grdAgenda.RowCount; i++)
                {
                    TimeSpan horaCeldaGrilla = TimeSpan.Parse(grdAgenda.Rows[i].Cells["HoraDia"].Value.ToString());
                    if (item.HoraTurno == horaCeldaGrilla)
                    {
                        int nroDia = 0;
                        switch (item.FechaTurno.DayOfWeek)
                        {
                            case DayOfWeek.Friday:
                                nroDia = 5;
                                break;
                            case DayOfWeek.Monday:
                                nroDia = 1;
                                break;
                            case DayOfWeek.Saturday:
                                nroDia = 6;
                                break;
                            case DayOfWeek.Sunday:
                                nroDia = 7;
                                break;
                            case DayOfWeek.Thursday:
                                nroDia = 4;
                                break;
                            case DayOfWeek.Tuesday:
                                nroDia = 2;
                                break;
                            case DayOfWeek.Wednesday:
                                nroDia = 3;
                                break;
                        }
                        grdAgenda.Rows[i].Cells[nroDia].Style.BackColor = Color.White;
                        break;
                    }
                }
            }
        }

        private TimeSpan obtenerHoraInicioMasTemprana(List<Turno> listTurnos)
        {
            TimeSpan horaMasTempranaInicio = new TimeSpan(20, 0, 0);
            foreach (Turno item in listTurnos)
            {
                if (item.HoraTurno < horaMasTempranaInicio)
                    horaMasTempranaInicio = item.HoraTurno;
            }
            return horaMasTempranaInicio;
        }

        private TimeSpan obtenerHoraFinMasTardia(List<Turno> listTurnos)
        {
            TimeSpan horaMasTardiaFin = new TimeSpan(8, 0, 0);
            foreach (Turno item in listTurnos)
            {
                if (item.HoraTurno > horaMasTardiaFin)
                    horaMasTardiaFin = item.HoraTurno;
            }
            return horaMasTardiaFin;
        }

        private bool validarDatos()
        {
            bool res = true;
            string error = "";
            if (cmbEspecialidad.SelectedValue == null)
            {
                error += "Debe seleccionarse especialidad \n\r";
                res = false;
            }
            if (cmbMedico.SelectedValue == null)
            {
                error += "Debe seleccionarse médico \n\r";
                res = false;
            }
            if (!rdb1Mes.Checked && !rdb2Meses.Checked && !rdb3Meses.Checked)
            {
                error += "Debe elegirse el período para generar la agenda";
                res = false;
            }

            if (!res)
                MessageBox.Show(error, "Aviso", MessageBoxButtons.OK);
            return res;
        }

        private void btnCancelar_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

        private void btnLimpiar_Click(object sender, EventArgs e)
        {
            limpiar();
        }

        private void limpiar()
        {
            if (grdAgenda.RowCount > 0)
            {
                grdAgenda.Rows.Clear();
                btnGenerar.Enabled = true;
            }
            cmbEspecialidad.SelectedIndex = -1;
            txtUltimaFechaAgenda.Text = "";
            rdb1Mes.Checked = false;
            rdb2Meses.Checked = false;
            rdb3Meses.Checked = false;
        }

        private void btnAceptar_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Agenda generada!");
            DialogResult dr = MessageBox.Show("Desea generar una nueva agenda?", "Confirmar", MessageBoxButtons.OKCancel);
            if (dr == DialogResult.OK)
            {
                limpiar();
            }
            else
            {
                this.Dispose();
            }
            
        }







    }
}
